/*
 * Copyright (c) 2007 centrevillage <centrevillage@gmail.com>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
// std
#include <vector>

// boost
#include <boost/format.hpp>
#include <boost/variant.hpp>

// seq
#include "MidiMsg.h"

using namespace std;
using namespace boost;

namespace seq {

MidiMsg::MidiMsg(const vector<BYTE>& data) {
    data_ = data;
}

MidiMsg::MidiMsg(BYTE code, BYTE channel, BYTE data1, BYTE data2) {
    data_ = (data2 << 16) | (data1 << 8) | code | (channel & 0x0F);
    //data_ = ((code | (channel & 0x0F)) << 24) | (data1 << 16) | (data2 << 8);
	//data_ = MAKELONG(MAKEWORD(code | channel ,data1),MAKEWORD(data2,0));
}

MidiMsg::MidiMsg(UINT32 data) : data_(data) {
}

MidiMsg::~MidiMsg() {}

UINT32 MidiMsg::getMsg() const {
    return get<UINT32>(data_);
}

const vector<BYTE>& MidiMsg::getMsgList() const {
    return get< vector<BYTE> >(data_);
}

bool MidiMsg::isValid() const {
    if (isLong()) {
        return !get< vector<BYTE> >(data_).empty();
    } else {
        return get<UINT32>(data_) ? true : false;
    }
}

bool MidiMsg::isLong() const {return data_.which() == 1;}

string MidiMsg::toString() const {
    if (isLong()) {
        return "Long Message";
    }
    return io::str(format("%#02x") % get<UINT32>(data_));
}

bool operator== (const MidiMsg& lhs, const MidiMsg& rhs) {
    if (lhs.isLong()) {
        return rhs.isLong() && lhs.getMsgList() == rhs.getMsgList();
    }
    return !rhs.isLong() && lhs.getMsg() == rhs.getMsg();
}

bool operator!= (const MidiMsg& lhs, const MidiMsg& rhs) {
    return !(lhs == rhs);
}

MidiMsg createMidiMsg(BYTE status, BYTE data1, BYTE data2) {
    UINT32 data = (data2 << 16) | (data1 << 8) | status;
    return MidiMsg(data);
}

} // end of namespace seq
